package com.slorgs.business.service.impl

import com.alibaba.fastjson.JSON
import com.baomidou.mybatisplus.core.metadata.IPage
import com.baomidou.mybatisplus.extension.plugins.pagination.Page
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl
import com.gateway.common.Constants
import com.gateway.common.dto.ProcessDTO
import com.gateway.common.enums.Cmpt
import com.gateway.common.enums.MessageType
import com.slorgs.business.mq.MessageProducer
import com.slorgs.business.service.ApiService
import com.slorgs.business.utils.G711CodeUtil
import com.slorgs.business.utils.ThreadLocalUtil
import com.slorgs.business.utils.TokenUtil
import com.slorgs.infrastructure.dto.*
import com.slorgs.infrastructure.mapper.ApiMapper
import com.slorgs.infrastructure.model.Api
import com.slorgs.web.config.WebAuthInterceptor.Companion.buildUser
import org.apache.commons.lang3.StringUtils
import org.slf4j.LoggerFactory
import org.springframework.http.HttpStatus
import org.springframework.stereotype.Service
import org.springframework.transaction.TransactionStatus
import org.springframework.transaction.support.TransactionTemplate
import org.springframework.web.multipart.MultipartFile
import sun.misc.BASE64Encoder
import java.io.File
import java.util.*
import javax.annotation.Resource
import javax.servlet.http.HttpServletRequest

@Service
class ApiServiceImpl : ServiceImpl<ApiMapper, Api>(), ApiService {

    companion object {
        private val log = LoggerFactory.getLogger(ApiServiceImpl::class.java)
    }

    @Resource
    private var messageProducer: MessageProducer? = null

    @Resource
    private var transactionTemplate: TransactionTemplate? = null

    @Resource
    private var apiMapper: ApiMapper? = null

    override fun selectList(page: Page<*>?, api: Api?): ResponseDTO {
        val responseDTO = ResponseDTO()
        try {
            val iPage: IPage<ApiDTO?>? = apiMapper?.selectList(Page<ApiDTO>(page!!.current, page.size), api)
            responseDTO.data = iPage
        } catch (e: Exception) {
            responseDTO.code = HttpStatus.BAD_REQUEST.value()
            responseDTO.message = "拉取列表出现异常"
            log.error("拉取列表出现异常...", e)
        }
        return responseDTO
    }

    override fun groupList(): ResponseDTO {
        val responseDTO = ResponseDTO()
        responseDTO.data = apiMapper!!.selectGroup()
        return responseDTO
    }

    override fun apiList(api: ApiGroupDTO?, page: Page<*>?, request: HttpServletRequest?): ResponseDTO {
        val responseDTO = ResponseDTO()
        var token = ""
//        if (request!!.getHeader("token").also { token = it } != null && request.getHeader("token") != "null") {
//            try {
//                if (StringUtils.isNotEmpty(token)) {
//                    token = token.replace("XDeep", "")
//                }
//                val map: Map<String, String> = TokenUtil.parseToken(token)
//                ThreadLocalUtil.put("CURRENT_USER", buildUser(map))
//            } catch (e: java.lang.Exception) {
//                log.info("没有登陆")
//            }
//        }
        responseDTO.data =
            apiMapper?.selectApiList(
                Page<Any>(page!!.current, page.size), api,
                "admin" == if (ThreadLocalUtil.getUser() == null) null else ThreadLocalUtil.getUser()?.role,
                ThreadLocalUtil.getUser()?.loginName
            )
        return responseDTO
    }

    override fun addOrDelete(api: Api?): ResponseDTO? {
        val responseDTO = ResponseDTO()
        return transactionTemplate?.execute { status: TransactionStatus ->
            try {
                if (org.springframework.util.StringUtils.isEmpty(api!!.idApi)) {
                    apiMapper!!.insert(
                        Api.builder()
                            .idApi(UUID.randomUUID().toString().replace("-".toRegex(), "")).apiName(api.apiName)
                            .createBy(ThreadLocalUtil.getUser()?.loginName).createTime(Date())
                            .model(api.model).path(api.path).limiting(api.limiting).build()
                    )
                    responseDTO.message = "新建API成功"
                } else {
                    apiMapper!!.updateById(
                        Api.builder().idApi(api.idApi)
                            .updateBy(ThreadLocalUtil.getUser()!!.loginName).updateTime(Date())
                            .limiting(api.limiting).path(api.path).model(api.model).apiName(api.apiName).build()
                    )
                    responseDTO.message = "更改API成功"
                }
            } catch (e: java.lang.Exception) {
                log.error("更新或新建API出现异常...", e)
                responseDTO.message = "更新或新建API出现异常"
                responseDTO.code = HttpStatus.BAD_REQUEST.value()
                status.setRollbackOnly()
            }
            responseDTO
        }
    }

    override fun addApi(api: com.gateway.common.model.Api?): ResponseDTO? {
        val responseDTO = ResponseDTO()
        val map: MutableMap<String, String> = HashMap()
        var uid = api!!.idApi
        return try {
            if (org.springframework.util.StringUtils.isEmpty(api.idApi)) {
                uid = UUID.randomUUID().toString().replace("-".toRegex(), "")
                api.idApi = uid
                api.createBy = ThreadLocalUtil.getUser()!!.loginName
                api.createTime = Date()
                api.available = true
                api.version = 1.0f
                api.process = processDefinition(JSON.parseObject(api.process, ProcessDTO::class.java))
                apiMapper!!.insertApi(api)
            } else {
                if (StringUtils.isNoneEmpty(api.process)) api.process =
                    processDefinition(JSON.parseObject(api.process, ProcessDTO::class.java))
                api.updateBy = ThreadLocalUtil.getUser()!!.loginName
                api.updateTime = Date()
                apiMapper!!.update(api)
            }
            map["idApi"] = uid
            map["operation"] = "load"
            map["type"] = MessageType.API_CACHE.name
            val sendResult = messageProducer!!.sendMessage(Constants.API_CACHE_TOPIC, JSON.toJSONString(map))
            responseDTO.message = "操作成功"
            if (!sendResult!!.code.equals(HttpStatus.OK.value())) {
                responseDTO.message = "虽然操作成功，但是同步缓存失败；异常为: " + sendResult.message
            }
            responseDTO
        } catch (e: java.lang.Exception) {
            log.error("添加或修改API出现异常", e)
            responseDTO.code = HttpStatus.INTERNAL_SERVER_ERROR.value()
            responseDTO.message = "操作失败"
            responseDTO
        }
    }

    private fun processDefinition(processDTO: ProcessDTO): String? {
        val components = processDTO.components
        val collect: Set<Cmpt> = HashSet(components)
        components.clear()
        if (collect.contains(Cmpt.LOG_COMPONENT)) components.add(Cmpt.LOG_COMPONENT)
        if (collect.contains(Cmpt.AUTHENTICATION_COMPONENT)) components.add(Cmpt.AUTHENTICATION_COMPONENT)
        if (collect.contains(Cmpt.LIMITING_COMPONENTS)) components.add(Cmpt.LIMITING_COMPONENTS)
        if (collect.contains(Cmpt.ROUTING_COMPONENT)) components.add(Cmpt.ROUTING_COMPONENT)
        if (collect.contains(Cmpt.SMS_COMPONENT)) components.add(Cmpt.SMS_COMPONENT)
        if (collect.contains(Cmpt.CACHE_COMPONENT)) components.add(Cmpt.CACHE_COMPONENT)
        processDTO.components = components
        return JSON.toJSONString(processDTO)
    }

    override fun refreshCache(id: String?): ResponseDTO {
        val responseDTO = ResponseDTO()
        val map: MutableMap<String, String> = HashMap()
        map["idApi"] = id!!
        map["type"] = MessageType.API_CACHE.name
        map["operation"] = "load"
        map["cmpt"] = "true"
        val sendResult = messageProducer!!.sendMessage(Constants.API_CACHE_TOPIC, JSON.toJSONString(map))
        responseDTO.message = "更新缓存成功"
        if (!sendResult!!.code.equals(HttpStatus.OK.value())) {
            responseDTO.message = "更新缓存失败;异常为: " + sendResult.message
            responseDTO.code = 500
        }
        return responseDTO
    }

    override fun deleteApi(id: String?): ResponseDTO? {
        val responseDTO = ResponseDTO()
        val map: MutableMap<String, String> = HashMap()
        return transactionTemplate?.execute { transactionStatus: TransactionStatus ->
            try {
                apiMapper!!.deleteApiById(id)
                apiMapper!!.deleteLinkLogByApi(id)
                apiMapper!!.deleteApiMappingApp(id)
                map["idApi"] = id!!
                map["operation"] = "delete"
                map["type"] = MessageType.API_CACHE.name
                messageProducer!!.sendMessage(Constants.API_CACHE_TOPIC, JSON.toJSONString(map))
                responseDTO.message = "删除成功"
            } catch (e: java.lang.Exception) {
                log.error("删除Api出现异常...", e)
                responseDTO.message = "删除Api出现异常"
                responseDTO.code = HttpStatus.BAD_REQUEST.value()
                transactionStatus.setRollbackOnly()
            }
            responseDTO
        }
    }

    override fun pcmToPcmA(file: MultipartFile?, apiDTO: PcmApiDTO?): ResponseDTO? {
        val responseDTO = ResponseDTO()
        try {
            var encode: String? = null
            when (apiDTO!!.convertFormat) {
                "0" -> if (!apiDTO!!.isNewline) encode = BASE64Encoder().encode(
                    G711CodeUtil.G711aEncoder(
                        file!!.bytes, ByteArray(file!!.bytes.size / 2), file!!.bytes.size / 2
                    )
                ) else encode = BASE64Encoder().encode(
                    G711CodeUtil.G711aEncoder(
                        file!!.bytes, ByteArray(file!!.bytes.size / 2), file!!.bytes.size / 2
                    )
                ).replace("\n".toRegex(), "")

                "1" -> if (!apiDTO!!.isNewline) encode = BASE64Encoder().encode(
                    G711CodeUtil.G711uEncoder(
                        file!!.bytes, ByteArray(
                            file!!.bytes.size / 2
                        ), file!!.bytes.size / 2
                    )
                ) else encode = BASE64Encoder().encode(
                    G711CodeUtil.G711uEncoder(
                        file!!.bytes, ByteArray(file!!.bytes.size / 2), file!!.bytes.size / 2
                    )
                ).replace("\n".toRegex(), "")
            }
            responseDTO.data = encode
            responseDTO.message = "转换完成"
        } catch (e: java.lang.Exception) {
            log.error("音频格式转换出现异常...", e)
            responseDTO.code = HttpStatus.BAD_REQUEST.value()
            responseDTO.message = "音频格式转换出现异常"
        }
        return responseDTO
    }

    override fun picZip(file: MultipartFile?): ResponseDTO? {
        try {
            file!!.transferTo(File(""))
        } catch (e: java.lang.Exception) {
            log.error(e.message)
        }
        return null
    }


    override fun envList(): ResponseDTO? {
        return ResponseDTO.builder().code(200).data(apiMapper!!.selectEnv()).build()
    }

    override fun auditLog(page: Page<*>?, loggerDTO: LinkLoggerDTO?): ResponseDTO? {
        val loggerIPage: IPage<LinkLoggerDTO?>? = apiMapper?.selectApiAuditByApi(
            Page<LinkLoggerDTO>(page!!.current, page.size), loggerDTO!!.idApi, loggerDTO.status, loggerDTO.name
        )
        return ResponseDTO.builder().code(200).data(loggerIPage).message("获取成功").build()
    }

    override fun checkApiPath(path: String?): ResponseDTO {
        val responseDTO = ResponseDTO()
        val i = apiMapper!!.selectApiPathCount(path)
        if (i > 0) {
            responseDTO.message = "路径不可用"
            responseDTO.code = 500
        }
        return responseDTO
    }

    override fun onlineEnv(apiEnvDTO: ApiEnvDTO?): ResponseDTO {
        val responseDTO = ResponseDTO()
        try {
            var jsonString = JSON.toJSONString(apiEnvDTO!!.idEnv).replace("\\[".toRegex(), "")
            jsonString = jsonString.replace("]".toRegex(), "")
            jsonString = jsonString.replace("\"".toRegex(), "")
            apiMapper!!.update(com.gateway.common.model.Api.builder().idApi(apiEnvDTO.idApi).env(jsonString).build())
            val map: MutableMap<String, String> = HashMap()
            map["idApi"] = apiEnvDTO.idApi
            map["operation"] = "load"
            map["type"] = MessageType.API_CACHE.name
            messageProducer!!.sendMessage(Constants.API_CACHE_TOPIC, JSON.toJSONString(map))
        } catch (e: java.lang.Exception) {
            log.error("上线多环境出现异常...", e)
            responseDTO.message = "上线多环境出现异常" + e.message
        }
        return responseDTO
    }

    override fun statistics(): ResponseDTO {
        val responseDTO = ResponseDTO()
        val objects: MutableList<Any?> = ArrayList()
        val statistics = apiMapper!!.statistics()
        val successRate = apiMapper!!.success_rate()
        val apiCountDTOS = apiMapper!!.countByApi()
        objects.add(successRate)
        objects.add(statistics)
        objects.add(apiCountDTOS)
        responseDTO.data = objects
        return responseDTO
    }

    override fun saveLog(): ResponseDTO? {
        TODO("Not yet implemented")
    }
}